package org.makcro.sms.services.chat.base.filters;

import java.text.MessageFormat;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Random;

import org.apache.log4j.Logger;
import org.makcro.sms.services.chat.base.dao.ChatMemberDao;
import org.makcro.sms.services.chat.base.dao.SubscriberDao;
import org.makcro.sms.services.chat.model.ChatMember;
import org.makcro.sms.services.chat.model.Question;
import org.makcro.sms.services.chat.model.Subscriber;

import com.klikmee.sms.cef.services.Service;

/**
 * Subscribes customer to list of available people for chat. After subscription
 * list of available people aliases is sent back to the subscriber.
 * 
 * @author makcro
 * 
 */
public class SubscriptionFilter extends AbstractFilter {

	/**
	 * Core id of the subscription service
	 */
	private Long			subsciptionServiceId;

	/**
	 * charging for the subscription message response
	 */
	private Long			chargingId;
	/**
	 * Logger instance
	 */
	private Logger			logger			= Logger.getLogger( SubscriptionFilter.class );

	/**
	 * Reference to the {@link ChatMember} DAO service
	 */
	private ChatMemberDao	chatMemberDao	= null;

	/**
	 * String template for the reply message
	 */
	private String			messageTemplate	= null;

	/**
	 * Instance of subsciber dao used to register new / update subscribers
	 */
	private SubscriberDao	subscriberDAO	= null;

	/**
	 * number of chat members to return to subscriber
	 */
	private int				answerListSize;

	/**
	 * Subscribes customer to members list. Activates on request text and
	 * keyword successful match.
	 * 
	 * @return true if customer is subscribed, false otherwise
	 */
	@Override
	public boolean process(Question question) {

		// test if question matches keyword expression
		if (question.getQuestion().matches( activationExpression )) {

			logger.info( MessageFormat.format( "Successful activatoin match on subscription filter message id = [{0}]", question.getCoreID() ) );

			// create / update subscription
			createOrUpdateSubscription( question.getFromNumber() );
			// prepare answer text
			String messageText = createMessageBody();
			// send the answer
			Long coreId = this.coreAdapter.sendMessage( chargingId, subsciptionServiceId, Service.SERVICE_FLAG_SEMANTIC_OK, question.getCoreID(), messageText );

			// update question so it's not visible to operaters
			question.setVisable( false );

			// create answer object, question create will cascade
			persistAnswer( question, messageText, coreId, false );

			return true;
		}

		return false;
	}

	/**
	 * Creates / updates subscriber identified by it's phone number.
	 * 
	 * @param phonenumber
	 */
	private void createOrUpdateSubscription(String phonenumber) {
		// try to find subscriber by it's phonenumber
		Subscriber subscriber = this.subscriberDAO.findByPhonenumber( phonenumber );
		// if it's not found, create new
		if (subscriber == null) {
			subscriber = new Subscriber();
			subscriber.setPhonenumber( phonenumber );
			subscriber.setSubscriptionDate( new Date() );

			logger.info( MessageFormat.format( "Created new subscriber with phone number [{0}]", phonenumber ) );
		}
		// if is found, extend his subscription
		else {
			subscriber.setUnsubscribed( false );
			subscriber.setSubscriptionDate( new Date() );

			logger.info( MessageFormat.format( "Extened subsription for phone number [{0}]", phonenumber ) );
		}

		subscriberDAO.edit( subscriber );
	}

	private String createMessageBody() {
		// load all members from database
		List<String> allMembersAliases = chatMemberDao.findAllMembersAliases();
		// shuffle list
		Collections.shuffle( allMembersAliases );
		// randomize number of names returned limited by answer list size
		Random random = new Random();
		int listSize = 2 + random.nextInt( getAnswerListSize() - 2 ) + 1;
		int limit = listSize > allMembersAliases.size() ? allMembersAliases.size() : listSize;

		List<String> truncated = allMembersAliases.subList( 0, limit );

		String memberAliases = org.apache.commons.lang.StringUtils.join( truncated, ',' );

		String messageText = MessageFormat.format( getMessageTemplate(), memberAliases );
		return messageText;
	}

	public void setChatMemberDao(ChatMemberDao chatMemberDao) {
		this.chatMemberDao = chatMemberDao;
	}

	public void setMessageTemplate(String messageTemplate) {
		this.messageTemplate = messageTemplate;
	}

	public void setAnswerListSize(int answerListSize) {
		this.answerListSize = answerListSize;
	}

	public String getMessageTemplate() {
		return messageTemplate;
	}

	public int getAnswerListSize() {
		return answerListSize;
	}

	public void setSubsciptionServiceId(Long subsciptionServiceId) {
		this.subsciptionServiceId = subsciptionServiceId;
	}

	public void setChargingId(Long chargingId) {
		this.chargingId = chargingId;
	}

	public void setSubscriberDAO(SubscriberDao subscriberDAO) {
		this.subscriberDAO = subscriberDAO;
	}

	@Override
	public String toString() {
		return "SubscriptionFilter";
	}

}
